import fs from "fs"
import path from "path"
import request from "request"
import { IEnum, IEnumObj, IJson } from "../interface/type"

const COMP_NAMES = {
  select: 'el-select',
  number: 'el-input-number',
  date: 'el-date-picker',
  input: 'el-input',
  switchComp: 'el-switch',
  cascader: 'el-cascader',
  checkGroup: 'el-checkbox-group',
  radioGroup: 'el-radio-group',
  staff: 'co-staff-query',
  address: 'co-address',
  pdf: 'co-pdf-upload',
  image: 'co-image-upload',
  store: 'co-store-query-select'
}

// 首字母大写
function firstUp(str: string) {
  return str.replace(/( |^)[a-z]/g, (L) => L.toUpperCase());
}

// 首字母小写
function firstLower(str: string) {
  return str.replace(/( |^)[A-Z]/g, (L) => L.toLowerCase());
}

// 横线转大写
function lineToUp(name: string) {
  let arr = name.split('-');
  arr = arr.map(it => {
    return firstUp(it)
  })
  return arr.join('')
}

function getFunNameFromPath(pathStr: string) {
  const arr: string[] = pathStr.split('/');
  return arr[arr.length - 1];
}

function upToLine(fileName: string) {
  const newfileName = fileName.replace(/( |^)[A-Z]/g, (L) => L.toLowerCase());
  return newfileName.replace(/([A-Z])/g, '-$1').toLowerCase()
}

function upToDownLine(str: string) {
  const name = str.replace(/( |^)[A-Z]/g, (L) => L.toLowerCase());
  return name.replace(/([A-Z])/g, '_$1').toUpperCase()
}

// 递归创建目录
function mkdirs(directory: any, callback: () => void) {
  const exists: boolean = fs.existsSync(directory);
  if (exists) {
    callback();
  } else {
    mkdirs(path.dirname(directory), () => {
      fs.mkdirSync(directory);
      callback();
    });
  }
}

// 确认目录是否存在，不存在就创建
function dotExistDirectoryCreate(directory: string) {
  return new Promise((resolve) => {
    mkdirs(directory, () => {
      resolve(true);
    });
  });
}

function resolvePath(...file: any[]) {
  return path.resolve(__dirname, ...file)
}

// 确认目录generatorg下面子目录是否存在，不存在就创建
async function checkAndCreatePath(secondPath: string = '') {
  const filePath = resolvePath(`../../generator${secondPath}`)
  console.log('filePath: ', filePath)
  const enumsFilePathExists = fs.existsSync(filePath);
  if (!enumsFilePathExists) {
    console.log(`正在生成  目录 ${filePath}`);
    await dotExistDirectoryCreate(filePath);
  }
  return filePath
}

// 生成文件
function generateFile(filePath: string, data: any) {
  if (fs.existsSync(filePath)) {
    console.error(`${filePath}文件已存在`);
    return;
  }
  return new Promise((resolve, reject) => {
    fs.writeFile(filePath, data, 'utf8', (err) => {
      if (err) {
        console.error(err);
        reject(err);
      } else {
        resolve(true);
      }
    })
  })
}

/**
 * 获取数据
 * @param packageName
 */
function requestGet(url: string): Promise<any> {
  return new Promise((resolve, reject) => request(url,
    (err: Error, _, body: any) => {
      // console.log('err, response, body: ', err, response, body)
      if (err) {
        console.log('这里获取数据失败', err)
        reject(err);
      } else {
        if (typeof body === 'string') {
          resolve(JSON.parse(body));
        } else {
          resolve(body);
        }
      }
    })
  )
}

/**
 * 从包名获取服务名
 * @param str
 */
function getLastNameFromPackage(str: string) {
  const arr: string[] = str.split('.')
  return arr[arr.length - 1]
}

function deleteNum(str: string) {
  if (str) {
    const reg = /[0-9]+/g;
    const str1 = str.replace(reg, '');
    return str1;
  }
  return '';
}

/**
 * 处理原格式的枚举 如：　促销状态：0测试中 1未开始 2进行中 3已结束 4已停用,可用
 * @param desc
 * @param enumArr
 */
function handleOldRuleEnum(desc: string, enumArr: string[]): IEnumObj {
  const enumClassArr: IEnum[] = [];
  let description: string = ''
  if (enumArr && enumArr.length > 0 && desc && desc.indexOf('：') > -1) {
    const descriptionArr = desc.split('：');
    description = descriptionArr[0]
    const dArr: string[] = descriptionArr[1].split(' ');
    enumArr.forEach((it, ix) => {
      let s = dArr[ix];
      s = deleteNum(s);
      enumClassArr.push({
        value: it,
        name: s,
      });
    });
  }
  return {
    description,
    enums: enumClassArr
  };
}

/**
 * 处理枚举
 * @param desc 门店状态: 0新建 1待营业 2营业中 3已闭店 99已删除
 * @param enumArr 枚举数组
 */
function handleBlankEnum(desc: string, enumArr: string[]): IEnumObj {
  const enumClassArr: IEnum[] = [];
  let description: string = ''
  if (enumArr && enumArr.length > 0 && desc && desc.indexOf(': ') > -1) {
    const descriptionArr = desc.split(': ');
    description = descriptionArr[0]
    const dArr = descriptionArr[1].split(' ');

    enumArr.forEach((it, ix) => {
      let s = dArr[ix];
      s = deleteNum(s);
      enumClassArr.push({
        value: it,
        name: s
      });
    });
  }
  return {
    description,
    enums: enumClassArr
  };
}

/**
 * 处理枚举
 * @param desc 审核状态:TOBE_EFFECT-1-待审核,OPENING-2-已撤回,REFUSED-3-审核驳回,CHECKED-4-已审核
 */
function handleEnum(desc: string, enumArr: string[]): IEnumObj {
  const enumClassArr: IEnum[] = [];
  let description: string = ''
  if (enumArr && enumArr.length > 0 && desc && desc.indexOf(':') > -1) {
    const descriptionArr = desc.split(':');
    description = descriptionArr[0]
    const dArr: string[] = descriptionArr[1].split(',');
    dArr.forEach(item => {
      const eArr: string[] = item.split('-')
      enumClassArr.push({
        value: eArr[0],
        name: eArr[2],
      });
    })
  }
  return {
    description,
    enums: enumClassArr
  };
}

// 查看字符串中是否包含关键字数组
function checkStrIncludeKeyWord(str: string, keyword: string[]): boolean {
  if (!str) return false
  const len: number = keyword.findIndex(item => {
    return item && str.indexOf(item) > -1
  })
  return len > -1
}

// 查看字符串中是否等于关键字数组
function checkStrEqualKeyWord(str: string, keyword: string[]): boolean {
  if (!str) return false
  const len: number = keyword.findIndex(item => {
    return str === item
  })
  return len > -1
}

// 处理描述，与后台约定，描述中':'前的部分为标题，后部分为注释
function getDescription(description: string): string[] {
  let arr: string[] = ['', '']
  if (!description) {
    return arr
  }
  if (description.indexOf('\n') > -1) {
    description = description.replace(/\n/g, '')
  }
  description = description.trim()
  if (description.indexOf(':') > 0) {
    arr = description.split(':')
  } else if (description.indexOf('：') > 0) {
    arr = description.split('：')
  } else {
    arr[0] = description
  }
  if (arr[0].indexOf(',') > 0) {
    arr[0] = arr[0].split(',')[0]
  }
  if (arr[0].indexOf('，') > 0) {
    arr[0] = arr[0].split('，')[0]
  }
  if (arr[0].indexOf(' ') > 0) {
    arr[0] = arr[0].split(' ')[0]
  }
  if (arr[1]) {
    arr[1] = ' // ' + arr[1]
  }
  return arr
}

// 去掉换行、前后空格
function trimStr (desc: string|null|undefined): string {
  if (!desc) {
    return ''
  }
  if (desc.indexOf('\n') > -1) {
    desc = desc.replace(/\n/g, '')
  }
  desc = desc.trim()
  return desc
}

// 根据描述获取标签名
function getNameFromDesc(desc: string | null | undefined): string {
  if (!desc) {
    return ''
  }
  if (desc.indexOf(',') > -1) {
    desc = desc.substr(0, desc.indexOf(','))
  }

  if (desc.indexOf('，') > -1) {
    desc = desc.substr(0, desc.indexOf('，'))
  }

  if (desc.indexOf(';') > -1) {
    desc = desc.substr(0, desc.indexOf(';'))
  }

  if (desc.indexOf('；') > -1) {
    desc = desc.substr(0, desc.indexOf('；'))
  }

  if (new RegExp(/\s+/g).test(desc)) {
    desc = desc.trim().split(" ")[0]
  }

  return desc
}

// 根据规则生成组件以及组件参数配置
function updateCompProp(item: IJson, key: string, upServerName: string): void {
  console.log('item >>> ', item)
  // const upServerName = firstLower(lineToUp(swaggerConfig.serverName))
  item.description = getNameFromDesc(item.description)
  item.compProps = ''
  if (item?.enum?.length > 0) {
    // 枚举
    item.component = COMP_NAMES.select
    item.compProps = `componentProps: {
        options: util.getEnumValues(${upServerName}Enum.${firstUp(key)}Enum, true)
      },
    `
    return
  }
  // 可以这里根据与后台的约定，输入对应的组件以及组件属性
  if (checkStrIncludeKeyWord(item.description, ['类型', '状态'])) {
    item.component = COMP_NAMES.select
    item.compProps = `componentProps: {
        options: util.getEnumValues(${upServerName}Enum.${firstUp(key)}Enum, true)
      },
    `
    return
  }
  item.type = ('' + item.type).toLowerCase()
  // 在这里可以根据描述，来指定对应的组件
  switch (item.type) {
    case 'bigdecimal':
      item.component = COMP_NAMES.number
      break
    case 'long':
    case 'integer': {
      // 一般来说搜索条件integer型是ＩＤ或编号类 [这里根据自己的项目，订制相应的组件]
      if (checkStrIncludeKeyWord(item.description, ['量', '值', '数'])) {
        item.component = COMP_NAMES.number
      } else if (checkStrIncludeKeyWord(item.description, ['员工', '店员', '创建人']) || item.name === 'staffId' || item.name === 'staffCode') {
        item.component = COMP_NAMES.staff
      } else if (checkStrIncludeKeyWord(item.description, ['地址']) ) {
        item.component = COMP_NAMES.address
        item.compProps = `componentProps: {
          baseColProps: {
            span: 18
          },
          showDetail: true
        }`
      } else if (checkStrIncludeKeyWord(item.description, ['图片'])) {
        item.component = COMP_NAMES.image
        item.compProps = `componentProps: {
          isEdit: false,
          baseColProps: {
            span: 24
          }
        }`
      } else {
        item.component = COMP_NAMES.select
        item.compProps = `componentProps: {
          options: []
        },
        `
      }
      break
    }
    case 'string': {
      if (item.format === 'date-time') {
        item.component = COMP_NAMES.date
      } else if (checkStrIncludeKeyWord(item.description, ['月份'])) {
        item.component = COMP_NAMES.date
        item.compProps = `componentProps: {
          type: 'month',
          placeholder: '请选择${ item.description}',
          valueFormat: 'yyyy-MM'
        },`
      } else if (checkStrIncludeKeyWord(item.description, ['城市'])) {
        item.component = COMP_NAMES.select
        item.compProps = `componentProps: {
          filterable: true,
          options: []
        },
        optionFunc: async () => {
          const res = await util.getEnumDictionary('DISTRICT_CODE')
          return res.list
        },
        `
      } else if (checkStrIncludeKeyWord(item.description, ['公司'])) {
        item.component = COMP_NAMES.select
        item.compProps = `componentProps: {
          filterable: true,
          options: []
        },
        optionFunc: async () => {
          const res = await util.getEnumDictionary('CLEARING_CORPORATION')
          return res.list
        },
        `
      } else if (checkStrIncludeKeyWord(item.description, ['门店', '店号'])) {
        item.component = COMP_NAMES.store
      } else {
        item.component = COMP_NAMES.input
        item.compProps = `componentProps: {
          placeholder: '请输入${ item.description}',
          maxLength: 50 // 可以设置默认最大长度
        },`
      }
      break
    }
    case 'boolean':
      item.component = COMP_NAMES.switchComp
      break
    case "number":
      item.component = COMP_NAMES.number
      break
    default: {
      item.component = COMP_NAMES.input
      item.compProps = `componentProps: {
        placeholder: '请输入${ item.description}',
        maxLength: 50 // 可以设置默认最大长度
      },`
      break
    }
  }
  // 如果是必填
  if (item.isReq) {
    const resType = item.component === COMP_NAMES.select ? '选择' : '输入'
    item.compProps = item.compProps + `
    dynamicRules: [
      { required: true, message: '请${resType}${item.description}', trigger: ['blur', 'change'] }
    ]`
  }
}

export default {
  firstUp,
  upToLine,
  upToDownLine,
  mkdirs,
  dotExistDirectoryCreate,
  resolvePath,
  checkAndCreatePath,
  generateFile,
  getLastNameFromPackage,
  requestGet,
  handleOldRuleEnum,
  handleBlankEnum,
  handleEnum,
  lineToUp,
  getFunNameFromPath,
  updateCompProp,
  firstLower,
  checkStrIncludeKeyWord,
  checkStrEqualKeyWord,
  getDescription,
  trimStr,
  getNameFromDesc,
  COMP_NAMES
}

